package com.hbisoft.pickit;

import com.ohos.asynctask.AsyncTask;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.app.Context;
import ohos.data.dataability.DataAbilityPredicates;
import ohos.data.resultset.ResultSet;
import ohos.utils.net.Uri;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.logging.Level;
import java.util.logging.Logger;

// 异步下载任务
class DownloadAsyncTask extends AsyncTask<Uri, Integer, String> {
    private Uri mUri;
    private CallBackTask callback;
    private WeakReference<Context> mContext;
    private String pathPlusName;
    private File folder;
    private ResultSet returnCursor;
    private InputStream is = null;
    private String errorReason = "";
    private WeakReference<AbilitySlice> abilityReference;

    DownloadAsyncTask(Uri uri, Context context, CallBackTask callback, AbilitySlice ability) {
        this.mUri = uri;
        mContext = new WeakReference<>(context);
        this.callback = callback;
        abilityReference = new WeakReference<>(ability);
    }

    @Override
    protected void onPreExecute() {
        callback.pickiTonUriReturned();
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        int post = values[0];
        callback.pickiTonProgressUpdate(post);
    }

    @Override
    protected String doInBackground(Uri... params) {
        File file = null;
        int size = -1;

        Context context = mContext.get();
        if (context != null) {
            folder = context.getExternalFilesDir("Temp");
            if (folder != null && !folder.exists()) {
                if (folder.mkdirs()) {
                    Logger.getLogger("PickiT : ").log(Level.INFO, "Temp folder createdd");
                }
            }
            try {
                returnCursor = DataAbilityHelper.creator(context).query(mUri, null, new DataAbilityPredicates());
            } catch (DataAbilityRemoteException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                is = DataAbilityHelper.creator(context).obtainInputStream(mUri);
            } catch (FileNotFoundException | DataAbilityRemoteException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // File is now available
        abilityReference.get().postTask(() -> callback.pickiTonPreExecute(), 0L);
        BufferedInputStream bis;
        FileOutputStream fos = null;
        try {
            try {
                if (returnCursor != null && returnCursor.goToFirstRow()) {
                    if (mUri.getScheme() != null)
                        if (mUri.getScheme().equals("content")) {
                            int sizeIndex = returnCursor.getColumnIndexForName("_size");
                            size = (int) returnCursor.getLong(sizeIndex);
                        } else if (mUri.getScheme().equals("file")) {
                            File ff = new File(mUri.getDecodedPath());
                            size = (int) ff.length();
                        }
                }
            } finally {
                if (returnCursor != null)
                    returnCursor.close();
            }

            try {
                pathPlusName = folder + "/" + getFileName(mUri, mContext.get());
            } catch (DataAbilityRemoteException e) {
                e.printStackTrace();
            }
            try {
                file = new File(folder + "/" + getFileName(mUri, mContext.get()));
            } catch (DataAbilityRemoteException e) {
                e.printStackTrace();
            }

            bis = new BufferedInputStream(is);
            fos = new FileOutputStream(file);

            byte[] data = new byte[1024];
            long total = 0;
            int count;
            while ((count = bis.read(data)) != -1) {
                if (!isCancelled()) {
                    total += count;
                    if (size != -1) {
                        try {
                            publishProgress((int) ((total * 100) / size));
                        } catch (Exception e) {
                            Logger.getLogger("PickiT -").log(Level.WARNING, "File size is less than 1");
                            publishProgress(0);
                        }
                    }
                    fos.write(data, 0, count);
                }
            }
        } catch (IOException e) {
            Logger.getLogger("Pickit IOException = ").log(Level.SEVERE, e.getMessage());
            errorReason = e.getMessage();
        } finally {
            try {
                fos.flush();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        assert file != null;
        try {
            return file.getCanonicalPath();
        } catch (Exception e) {
            Logger.getLogger("Pickit  getCanonicalPath Exception = ").log(Level.SEVERE, e.getMessage());
            return null;
        }
    }

    private String getFileName(Uri uri, Context context) throws DataAbilityRemoteException {
        String result = null;
        if (uri.getScheme() != null) {
            if (uri.getScheme().equals("content")) {
                ResultSet cursor = null;
                try {
                    cursor = DataAbilityHelper.creator(context).query(uri, null, new DataAbilityPredicates());

                    if (cursor != null && cursor.goToFirstRow()) {
                        result = cursor.getString(cursor.getColumnIndexForName("_display_name"));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (cursor != null) {
                        cursor.close();
                    }
                }
            }
        }
        if (result == null) {
            result = uri.getDecodedPath();
            assert result != null;
            int cut = result.lastIndexOf('/');
            if (cut != -1) {
                result = result.substring(cut + 1);
            }
        }
        return result;
    }

    protected void onPostExecute(String result) {
        if (result == null) {
            callback.pickiTonPostExecute(pathPlusName, true, false, errorReason);
        } else {
            callback.pickiTonPostExecute(pathPlusName, true, true, "");
        }
    }
}
